/*
 * Logger.h
 *
 *  Created on: 15.03.2013
 *      Author: mag
 */

#ifndef LOGGER_H_
#define LOGGER_H_

#include <stdio.h>
#include <stdarg.h>

#include "Thread.h"


#define DECLARE_LOG_SUPPORT_FUNC(module, level, func) \
		inline static void func(const char *fmt, ...) { \
			va_list va; va_start(va, fmt); \
			Logger::vlog(Logger::module, Logger::level, fmt, va); \
		}

#define DECLARE_LOG_SUPPORT(module) \
		DECLARE_LOG_SUPPORT_FUNC(module, VERBOSE, verbose) \
		DECLARE_LOG_SUPPORT_FUNC(module, DEBUG, debug) \
		DECLARE_LOG_SUPPORT_FUNC(module, LOG, log) \
		DECLARE_LOG_SUPPORT_FUNC(module, INFO, info) \
		DECLARE_LOG_SUPPORT_FUNC(module, ERROR, error) \
		DECLARE_LOG_SUPPORT_FUNC(module, FATAL, fatal) \
		static inline void ___log_nowarn2(); \
		static inline void ___log_nowarn1() { \
						___log_nowarn2(); verbose(""); debug(""); log(""); \
						                  info(""); fatal(""); error(""); } \
		static inline void ___log_nowarn2() { ___log_nowarn1(); } \

class Logger {
public:

	enum {
		APPLICATION	= 0x01,
		BACKEND		= 0x02,
		FPGA		= 0x04,
		MODULES		= 0x08,
		SCPI		= 0x10,
		SCPIBIND	= 0x10,
		HTTP		= 0x40,

		ALL_MODULES	= 0xfff

	} MODULE;

	enum {
		VERBOSE	= 0x20,
		DEBUG	= 0x10,
		LOG		= 0x08,
		INFO	= 0x04,
		ERROR	= 0x02,
		FATAL	= 0x01,

		INFORMATIVE 	= 0x001,		// informative message
		FPGA_MESSAGES 	= 0x002,		// fpga configuration
		FPGA_DATA 		= 0x004,		// fpga packages
		FPGA_RAW 		= 0x008,		// raw fpga package content
		START_STOP 		= 0x010,		// start/stop of iterators
		CORE_ERROR 		= 0x020,		// memory allocation failures
		ASSERTION_ERROR = 0x040,		// general assertion failure
		FPGA_ERROR 		= 0x080,		// error in fgpa communication

		QUIET 			= 0x001			// log only essential stuff
	} LOG_LEVEL;

	static void set_logfile(const char *);

	static void set_dumpfile(const char *);

	/** put message to logfile */
	static void log(int module, int lvl, const char* , ...);

	static void vlog(int module, int lvl, const char* , va_list ap);

	/** dump raw data to dumpfile */
	static void dump(size_t sz, void *buffer);

	/** shutdown, close logfiles */
	static void shutdown();

protected:
	static FILE *logfile, *dumpfile;
	static current_mutex log_mutex;
	static current_mutex dump_mutex;

	static size_t dump_size;
	static const size_t DUMP_THRESHHOLD=1024*256;

	static int log_mask;
};


#endif /* LOGGER_H_ */
